/*
 * Copyright (c) 2012 RTCLab
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 */

import flash.external.*;
import com.rtckit.*;
import flash.system.Security;
import mx.controls.*;
import flash.media.Microphone;

private var softphone:Softphone;
private var params:Object;
private var config:SoftphoneConfig;

public function appComplete(event:Event):void {
	Security.allowDomain('*');

	params = this.loaderInfo.parameters;
	
	if (params.debug)
		Logger.debugEnabled = true;
	Logger.writeMessage = writeMessage;
	
	config = new SoftphoneConfig(params);
	
	config.reportCallState = reportCallState;
	config.reportRegState = reportRegState;
	config.reportConnectState = reportConnectState;
	config.reportMicState = reportMicState;
	
	initGUI();

	softphone = new Softphone(config);
	
	setupCallbacks();
	
	config.setupMicrophone();
	
	if (params.onInitialized)
		ExternalInterface.call(params.onInitialized);
}

private function initGUI():void {
	if (config.video) {
		config.videoContainer = new VideoContainer(this, config.width, config.height, config.preview);
	} else if (params.displayText) {
		var label:Text = new Text();
		label.htmlText = params.displayText;
		label.setStyle('fontSize', 17);
		label.setStyle('textAlign', 'center');
		addChild(label);
	} else if (params.displayPicture) {
		var img:Image = new Image();
		img.load(params.displayPicture);
		addChild(img);
	}

	var myMenu:ContextMenu = new ContextMenu();
	myMenu.hideBuiltInItems();
	var powered:ContextMenuItem = new ContextMenuItem("Powered by RTCKit.com");
	powered.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT, visitSite);
	myMenu.customItems.push(powered);
	contextMenu = myMenu;
}

private function setupCallbacks():void {
	ExternalInterface.addCallback("connect", connect);
	ExternalInterface.addCallback("disconnect", disconnect);
	
	ExternalInterface.addCallback("register", register);
	ExternalInterface.addCallback("unregister", unregister);
	
	ExternalInterface.addCallback("call", call);
	ExternalInterface.addCallback("hangup", hangup);
	ExternalInterface.addCallback("answer", answer);
	ExternalInterface.addCallback("dial", dial);
	
	ExternalInterface.addCallback("showSettings", showSettings);
	ExternalInterface.addCallback("showMicDialog", showMicDialog);
	
	ExternalInterface.addCallback("listMicrophones", listMicrophones);
	ExternalInterface.addCallback("getMicIndex", getMicIndex);
	ExternalInterface.addCallback("setMicIndex", setMicIndex);
	
	ExternalInterface.addCallback("getMicGain", getMicGain);
	ExternalInterface.addCallback("setMicGain", setMicGain);
	ExternalInterface.addCallback("getVolume", getVolume);
	ExternalInterface.addCallback("setVolume", setVolume);
	
	ExternalInterface.addCallback("getQualityStats", getQualityStats);
}



private function writeMessage(msg:String, level:String):void {
	if (params.onMessage)
		ExternalInterface.call(params.onMessage, {text: msg, level: level});
}

private function visitSite(event:ContextMenuEvent):void {
	var url:String = "http://rtckit.com";
	var request:URLRequest = new URLRequest(url);
	try {
		navigateToURL(request, '_blank');
	} catch (e:Error) {
		Logger.error('Cannot navigate to URL');
	}
}

// javascript callbacks

private function connect(args:Object):void {
	softphone.connect(SoftphoneConfig.makeURL(args.server));
}

private function disconnect():void {
	softphone.disconnect();
}

private function checkParams(... args):Boolean {
	for (var i:int = 0; i < args.length; i++) {
		if (!args[i]) {
			Logger.error('Missing parameter');
			return false;
		}
		if (args[i].length > 255) {
			Logger.error('Params too long');
			return false;
		}
	}
	return true;
}

private function register(args:Object):void {
	if (!args.protocol)
		args.protocol = 'sip';
	var res:Boolean = false;
	switch (args.protocol) {
	case 'sip':
		res = checkParams(args.username, args.password, args.registrar);
		break;
	case 'jingle':
		res = checkParams(args.username, args.password, args.domain);
		break;
	case 'phone':
	case 'sipout':
		res = true;
	}
	if (!res)
		return;
	softphone.register(args);
}

private function unregister(args:Object):void {
	softphone.unregister(args);
}

private function call(args:Object):void {
	if (!checkParams(args.uri))
		return;
	softphone.call(args);
}

private function hangup(args:Object):void {
	if (!checkParams(args.uri))
		return;
	softphone.hangup(args);
}

private function answer(args:Object):void {
	if (!checkParams(args.uri))
		return;
	softphone.answer(args);
}

private function dial(args:Object):void {
	if (!checkParams(args.uri, args.digits))
		return;
	softphone.dial(args);
}

// softphone events

private function reportCallState(args:Object):void {
	if (args.state == 'INCOMING' || args.state == 'OUTGOING') {
		config.setupMicrophone();
		if (config.mic && config.mic.muted) {
			Security.showSettings("privacy");
		}
	}
	ExternalInterface.call(params.onCallState, args);
}

private function reportRegState(args:Object):void {
	ExternalInterface.call(params.onRegState, args);
}

private function reportConnectState(state:Boolean):void {
	if (params.onConnectState)
		ExternalInterface.call(params.onConnectState, {connected: state});
}

// microphone privacy

private function showSettings(panel:String = "privacy"):void {
	Security.showSettings(panel);
}

private function showMicDialog():void {
	if (!config.mic)
		return;
	config.mic.setLoopBack(true);
	config.mic.setLoopBack(false);
}

private function reportMicState(allowed:Boolean):void {
	if (params.onMicState)
		ExternalInterface.call(params.onMicState, {allowed: allowed});
}

private function getMicGain():Number {
	return config.getMicGain();
}

private function setMicGain(val:Number):void {
	config.setMicGain(val);
}

private function listMicrophones():Array {
	return Microphone.names;
}

private function getMicIndex():int {
	return config.getMicIndex();
}

private function setMicIndex(idx:int):void {
	config.setMicIndex(idx);
}

// volume

private function getVolume():Number {
	return config.getVolume();
}

private function setVolume(val:Number):void {
	config.setVolume(val);
}

// quality

private function getQualityStats():Object {
	return softphone.getQualityStats();
}
